/*     */ package com.zimbra.cs.filter;
/*     */ 
/*     */ import com.google.common.collect.ImmutableSet;
/*     */ import com.google.common.collect.Lists;
/*     */ import com.zimbra.common.mime.shim.JavaMailInternetAddress;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.Pair;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.IDNUtil;
/*     */ import com.zimbra.cs.filter.jsieve.ActionFlag;
/*     */ import com.zimbra.cs.filter.jsieve.ActionNotify;
/*     */ import com.zimbra.cs.filter.jsieve.ActionReply;
/*     */ import com.zimbra.cs.filter.jsieve.ActionTag;
/*     */ import com.zimbra.cs.mailbox.Folder;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.Message;
/*     */ import com.zimbra.cs.mailbox.Mountpoint;
/*     */ import com.zimbra.cs.mime.MPartInfo;
/*     */ import com.zimbra.cs.mime.Mime;
/*     */ import com.zimbra.cs.mime.ParsedMessage;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Arrays;
/*     */ import java.util.Collection;
/*     */ import java.util.Collections;
/*     */ import java.util.Enumeration;
/*     */ import java.util.HashSet;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Set;
/*     */ import java.util.StringTokenizer;
/*     */ import javax.mail.Header;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.internet.AddressException;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.mail.internet.MimePart;
/*     */ import org.apache.jsieve.CommandStateManager;
/*     */ import org.apache.jsieve.SieveContext;
/*     */ import org.apache.jsieve.exception.SieveException;
/*     */ import org.apache.jsieve.mail.Action;
/*     */ import org.apache.jsieve.mail.ActionFileInto;
/*     */ import org.apache.jsieve.mail.ActionKeep;
/*     */ import org.apache.jsieve.mail.ActionRedirect;
/*     */ import org.apache.jsieve.mail.MailAdapter;
/*     */ import org.apache.jsieve.mail.MailAdapter.Address;
/*     */ import org.apache.jsieve.mail.MailUtils;
/*     */ import org.apache.jsieve.mail.SieveMailException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ZimbraMailAdapter
/*     */   implements MailAdapter
/*     */ {
/*     */   private Mailbox mailbox;
/*     */   private FilterHandler handler;
/*     */   private String[] tags;
/*  77 */   private boolean allowFilterToMountpoint = true;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  83 */   private Set<String> filedIntoPaths = new HashSet();
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*  88 */   private static Set<String> addrHdrs = ImmutableSet.of("from", "sender", "to", "bcc", "cc", "reply-to", new String[0]);
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*  93 */   private List<Action> actions = new ArrayList();
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*  98 */   protected List<ItemId> addedMessageIds = new ArrayList();
/*     */   
/*     */   private SieveContext context;
/*     */   
/* 102 */   private boolean discardActionPresent = false;
/*     */   
/*     */   public ZimbraMailAdapter(Mailbox mailbox, FilterHandler handler) {
/* 105 */     this.mailbox = mailbox;
/* 106 */     this.handler = handler;
/*     */   }
/*     */   
/*     */   public void setAllowFilterToMountpoint(boolean allowFilterToMountpoint) {
/* 110 */     this.allowFilterToMountpoint = allowFilterToMountpoint;
/*     */   }
/*     */   
/*     */ 
/*     */   public Message getMessage()
/*     */   {
/*     */     try
/*     */     {
/* 118 */       return this.handler.getMessage();
/*     */     } catch (ServiceException e) {
/* 120 */       ZimbraLog.filter.warn("Unable to get Message", e);
/*     */     }
/* 122 */     return null;
/*     */   }
/*     */   
/*     */ 
/*     */   public ParsedMessage getParsedMessage()
/*     */   {
/*     */     try
/*     */     {
/* 130 */       return this.handler.getParsedMessage();
/*     */     } catch (ServiceException e) {
/* 132 */       ZimbraLog.filter.warn("Unable to get ParsedMessage.", e);
/*     */     }
/* 134 */     return null;
/*     */   }
/*     */   
/*     */ 
/*     */   public MimeMessage getMimeMessage()
/*     */   {
/*     */     try
/*     */     {
/* 142 */       return this.handler.getMimeMessage();
/*     */     } catch (ServiceException e) {
/* 144 */       ZimbraLog.filter.warn("Unable to get MimeMessage.", e);
/*     */     }
/* 146 */     return null;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void setContext(SieveContext context)
/*     */   {
/* 164 */     this.context = context;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public List<Action> getActions()
/*     */   {
/* 172 */     return this.actions;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void addAction(Action action)
/*     */   {
/* 181 */     this.actions.add(action);
/*     */   }
/*     */   
/*     */   public void executeActions() throws SieveException
/*     */   {
/*     */     try {
/* 187 */       this.handler.beforeFiltering();
/*     */       
/* 189 */       String messageId = Mime.getMessageID(this.handler.getMimeMessage());
/*     */       
/*     */ 
/*     */ 
/* 193 */       if (getActions().size() == 0) {
/* 194 */         ZimbraLog.filter.info("Discarding message with Message-ID %s from %s", new Object[] { messageId, Mime.getSender(this.handler.getMimeMessage()) });
/*     */         
/* 196 */         this.handler.discard();
/* 197 */         return;
/*     */       }
/*     */       
/* 200 */       if (getDeliveryActions().isEmpty())
/*     */       {
/* 202 */         if (getReplyNotifyActions().isEmpty())
/*     */         {
/*     */ 
/* 205 */           explicitKeep();
/* 206 */         } else if (!this.discardActionPresent)
/*     */         {
/*     */ 
/* 209 */           explicitKeep();
/*     */         }
/*     */       }
/*     */       
/* 213 */       for (Action action : this.actions) {
/* 214 */         if ((action instanceof ActionKeep)) {
/* 215 */           if (this.context == null) {
/* 216 */             ZimbraLog.filter.warn("SieveContext has unexpectedly not been set");
/* 217 */             doDefaultFiling();
/* 218 */           } else if (this.context.getCommandStateManager().isImplicitKeep())
/*     */           {
/*     */ 
/* 221 */             doDefaultFiling();
/*     */           } else {
/* 223 */             explicitKeep();
/*     */           }
/* 225 */         } else if ((action instanceof ActionFileInto)) {
/* 226 */           ActionFileInto fileinto = (ActionFileInto)action;
/* 227 */           String folderPath = fileinto.getDestination();
/*     */           try {
/* 229 */             if ((!this.allowFilterToMountpoint) && (isMountpoint(this.mailbox, folderPath))) {
/* 230 */               ZimbraLog.filter.info("Filing to mountpoint \"%s\" is not allowed.  Filing to the default folder instead.", new Object[] { folderPath });
/*     */               
/* 232 */               explicitKeep();
/*     */             } else {
/* 234 */               fileInto(folderPath);
/*     */             }
/*     */           } catch (ServiceException e) {
/* 237 */             ZimbraLog.filter.info("Unable to file message to %s.  Filing to %s instead.", folderPath, this.handler.getDefaultFolderPath(), e);
/*     */             
/* 239 */             explicitKeep();
/*     */           }
/* 241 */         } else if ((action instanceof ActionRedirect))
/*     */         {
/* 243 */           ActionRedirect redirect = (ActionRedirect)action;
/* 244 */           String addr = redirect.getAddress();
/* 245 */           ZimbraLog.filter.info("Redirecting message to %s.", new Object[] { addr });
/*     */           try {
/* 247 */             this.handler.redirect(addr);
/*     */           } catch (Exception e) {
/* 249 */             ZimbraLog.filter.warn("Unable to redirect to %s.  Filing message to %s.", addr, this.handler.getDefaultFolderPath(), e);
/*     */             
/* 251 */             explicitKeep();
/*     */           }
/* 253 */         } else if ((action instanceof ActionReply))
/*     */         {
/* 255 */           ActionReply reply = (ActionReply)action;
/* 256 */           ZimbraLog.filter.debug("Replying to message");
/*     */           try {
/* 258 */             this.handler.reply(reply.getBodyTemplate());
/*     */           } catch (Exception e) {
/* 260 */             ZimbraLog.filter.warn("Unable to reply.", e);
/* 261 */             explicitKeep();
/*     */           }
/* 263 */         } else if ((action instanceof ActionNotify)) {
/* 264 */           ActionNotify notify = (ActionNotify)action;
/* 265 */           ZimbraLog.filter.debug("Sending notification message to %s.", new Object[] { notify.getEmailAddr() });
/*     */           try {
/* 267 */             this.handler.notify(notify.getEmailAddr(), notify.getSubjectTemplate(), notify.getBodyTemplate(), notify.getMaxBodyBytes(), notify.getOrigHeaders());
/*     */ 
/*     */           }
/*     */           catch (Exception e)
/*     */           {
/*     */ 
/* 273 */             ZimbraLog.filter.warn("Unable to notify.", e);
/* 274 */             explicitKeep();
/*     */           }
/*     */         }
/*     */       }
/*     */       
/* 279 */       this.handler.afterFiltering();
/*     */     } catch (ServiceException e) {
/* 281 */       throw new ZimbraSieveException(e);
/*     */     }
/*     */   }
/*     */   
/*     */   private static boolean isMountpoint(Mailbox mbox, String folderPath) throws ServiceException
/*     */   {
/* 287 */     Pair<Folder, String> pair = mbox.getFolderByPathLongestMatch(null, 1, folderPath);
/* 288 */     Folder f = (Folder)pair.getFirst();
/* 289 */     return (f != null) && ((f instanceof Mountpoint));
/*     */   }
/*     */   
/*     */   private List<Action> getDeliveryActions() {
/* 293 */     List<Action> actions = new ArrayList();
/* 294 */     for (Action action : this.actions) {
/* 295 */       if (((action instanceof ActionKeep)) || ((action instanceof ActionFileInto)) || ((action instanceof ActionRedirect)))
/*     */       {
/*     */ 
/* 298 */         actions.add(action);
/*     */       }
/*     */     }
/* 301 */     return actions;
/*     */   }
/*     */   
/*     */   private List<ActionTag> getTagActions() {
/* 305 */     List<ActionTag> actions = new ArrayList();
/* 306 */     for (Action action : this.actions) {
/* 307 */       if ((action instanceof ActionTag)) {
/* 308 */         actions.add((ActionTag)action);
/*     */       }
/*     */     }
/* 311 */     return actions;
/*     */   }
/*     */   
/*     */   private List<ActionFlag> getFlagActions() {
/* 315 */     List<ActionFlag> actions = new ArrayList();
/* 316 */     for (Action action : this.actions) {
/* 317 */       if ((action instanceof ActionFlag)) {
/* 318 */         actions.add((ActionFlag)action);
/*     */       }
/*     */     }
/* 321 */     return actions;
/*     */   }
/*     */   
/*     */   private List<Action> getReplyNotifyActions() {
/* 325 */     List<Action> actions = new ArrayList();
/* 326 */     for (Action action : this.actions) {
/* 327 */       if (((action instanceof ActionReply)) || ((action instanceof ActionNotify))) {
/* 328 */         actions.add(action);
/*     */       }
/*     */     }
/* 331 */     return actions;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public Message doDefaultFiling()
/*     */     throws ServiceException
/*     */   {
/* 341 */     String folderPath = this.handler.getDefaultFolderPath();
/* 342 */     Message msg = null;
/* 343 */     if (this.filedIntoPaths.contains(folderPath)) {
/* 344 */       ZimbraLog.filter.info("Ignoring second attempt to file into %s.", new Object[] { folderPath });
/*     */     } else {
/* 346 */       msg = this.handler.implicitKeep(getFlagActions(), getTags());
/* 347 */       if (msg != null) {
/* 348 */         this.filedIntoPaths.add(folderPath);
/* 349 */         this.addedMessageIds.add(new ItemId(msg));
/*     */       }
/*     */     }
/* 352 */     return msg;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private Message explicitKeep()
/*     */     throws ServiceException
/*     */   {
/* 362 */     String folderPath = this.handler.getDefaultFolderPath();
/* 363 */     if (ZimbraLog.filter.isDebugEnabled()) {
/* 364 */       ZimbraLog.filter.debug(appendFlagTagActionsInfo("Explicit keep - fileinto " + folderPath, getFlagActions(), getTagActions()));
/*     */     }
/*     */     
/*     */ 
/* 368 */     Message msg = null;
/* 369 */     if (this.filedIntoPaths.contains(folderPath)) {
/* 370 */       ZimbraLog.filter.info("Ignoring second attempt to file into %s.", new Object[] { folderPath });
/*     */     } else {
/* 372 */       msg = this.handler.explicitKeep(getFlagActions(), getTags());
/* 373 */       if (msg != null) {
/* 374 */         this.filedIntoPaths.add(folderPath);
/* 375 */         this.addedMessageIds.add(new ItemId(msg));
/*     */       }
/*     */     }
/* 378 */     return msg;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private void fileInto(String folderPath)
/*     */     throws ServiceException
/*     */   {
/* 388 */     if (ZimbraLog.filter.isDebugEnabled()) {
/* 389 */       ZimbraLog.filter.debug(appendFlagTagActionsInfo("fileinto " + folderPath, getFlagActions(), getTagActions()));
/*     */     }
/*     */     
/* 392 */     if (this.filedIntoPaths.contains(folderPath)) {
/* 393 */       ZimbraLog.filter.info("Ignoring second attempt to file into %s.", new Object[] { folderPath });
/*     */     } else {
/* 395 */       ItemId id = this.handler.fileInto(folderPath, getFlagActions(), getTags());
/* 396 */       if (id != null) {
/* 397 */         this.filedIntoPaths.add(folderPath);
/* 398 */         this.addedMessageIds.add(id);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static String appendFlagTagActionsInfo(String deliveryActionInfo, Collection<ActionFlag> flagActions, Collection<ActionTag> tagActions)
/*     */   {
/* 405 */     StringBuilder builder = new StringBuilder(deliveryActionInfo);
/* 406 */     for (ActionFlag flagAction : flagActions) {
/* 407 */       builder.append(",Flag ").append(flagAction.getName());
/*     */     }
/* 409 */     for (ActionTag tagAction : tagActions) {
/* 410 */       builder.append(",Tag ").append(tagAction.getTagName());
/*     */     }
/* 412 */     return builder.toString();
/*     */   }
/*     */   
/*     */   private String[] getTags() {
/* 416 */     if (this.tags == null) {
/* 417 */       List<String> taglist = Lists.newArrayList();
/* 418 */       for (Action action : getTagActions()) {
/* 419 */         taglist.add(((ActionTag)action).getTagName());
/*     */       }
/* 421 */       this.tags = ((String[])taglist.toArray(new String[taglist.size()]));
/*     */     }
/* 423 */     return this.tags;
/*     */   }
/*     */   
/*     */   private List<String> handleIDN(String headerName, String[] headers)
/*     */   {
/* 428 */     List<String> hdrs = new ArrayList();
/* 429 */     for (String header : headers) {
/* 430 */       boolean altered = false;
/*     */       
/* 432 */       if (header.contains("xn--"))
/*     */       {
/* 434 */         StringTokenizer st = new StringTokenizer(header, ",;", true);
/* 435 */         StringBuffer addrs = new StringBuffer();
/* 436 */         while (st.hasMoreTokens()) {
/* 437 */           String address = st.nextToken();
/* 438 */           String delim = st.hasMoreTokens() ? st.nextToken() : "";
/*     */           try {
/* 440 */             javax.mail.internet.InternetAddress inetAddr = new JavaMailInternetAddress(address);
/* 441 */             String addr = inetAddr.getAddress();
/* 442 */             String unicodeAddr = IDNUtil.toUnicode(addr);
/* 443 */             if (unicodeAddr.equalsIgnoreCase(addr)) {
/* 444 */               addrs.append(address).append(delim);
/*     */             } else {
/* 446 */               altered = true;
/*     */               
/* 448 */               inetAddr.setAddress(unicodeAddr);
/* 449 */               addrs.append(inetAddr.toString()).append(delim);
/*     */             }
/*     */           } catch (AddressException e) {
/* 452 */             ZimbraLog.filter.warn("handleIDN encountered invalid address " + address + "in header " + headerName);
/* 453 */             addrs.append(address).append(delim);
/*     */           }
/*     */         }
/*     */         
/*     */ 
/* 458 */         if (altered) {
/* 459 */           String unicodeAddrs = addrs.toString();
/* 460 */           ZimbraLog.filter.debug("handleIDN added value " + unicodeAddrs + " for header " + headerName);
/* 461 */           hdrs.add(unicodeAddrs);
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 466 */       hdrs.add(header);
/*     */     }
/*     */     
/*     */ 
/* 470 */     return hdrs;
/*     */   }
/*     */   
/*     */   public List<String> getHeader(String name)
/*     */   {
/*     */     MimeMessage msg;
/*     */     try {
/* 477 */       msg = this.handler.getMimeMessage();
/*     */     } catch (ServiceException e) {
/* 479 */       ZimbraLog.filter.warn("Unable to get MimeMessage.", e);
/* 480 */       return Collections.emptyList();
/*     */     }
/*     */     
/* 483 */     String[] headers = Mime.getHeaders(msg, name);
/* 484 */     if (headers == null) {
/* 485 */       return Collections.emptyList();
/*     */     }
/*     */     
/* 488 */     if (addrHdrs.contains(name.toLowerCase())) {
/* 489 */       return handleIDN(name, headers);
/*     */     }
/* 491 */     return Arrays.asList(headers);
/*     */   }
/*     */   
/*     */   public List<String> getHeaderNames() throws SieveMailException
/*     */   {
/* 496 */     Set<String> headerNames = new HashSet();
/*     */     MimeMessage msg;
/*     */     try {
/* 499 */       msg = this.handler.getMimeMessage();
/*     */     } catch (ServiceException e) {
/* 501 */       ZimbraLog.filter.warn("Unable to get MimeMessage.", e);
/* 502 */       return Collections.emptyList();
/*     */     }
/*     */     
/*     */     try
/*     */     {
/* 507 */       Enumeration<Header> allHeaders = msg.getAllHeaders();
/* 508 */       while (allHeaders.hasMoreElements()) {
/* 509 */         headerNames.add(((Header)allHeaders.nextElement()).getName());
/*     */       }
/* 511 */       return new ArrayList(headerNames);
/*     */     } catch (MessagingException ex) {
/* 513 */       throw new SieveMailException(ex);
/*     */     }
/*     */   }
/*     */   
/*     */   public List<String> getMatchingHeader(String name) throws SieveMailException
/*     */   {
/* 519 */     return MailUtils.getMatchingHeader(this, name);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public Set<String> getMatchingHeaderFromAllParts(String name)
/*     */     throws SieveMailException
/*     */   {
/* 529 */     Set<String> values = new HashSet();
/*     */     try
/*     */     {
/* 532 */       MimeMessage msg = this.handler.getMimeMessage();
/* 533 */       for (MPartInfo partInfo : Mime.getParts(msg)) {
/* 534 */         MimePart part = partInfo.getMimePart();
/* 535 */         values.addAll(Arrays.asList(Mime.getHeaders(part, name)));
/*     */       }
/*     */     } catch (Exception e) {
/* 538 */       throw new SieveMailException("Unable to match attachment headers.", e);
/*     */     }
/*     */     
/* 541 */     return values;
/*     */   }
/*     */   
/*     */   public int getSize()
/*     */   {
/* 546 */     return this.handler.getMessageSize();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public List<ItemId> getAddedMessageIds()
/*     */   {
/* 554 */     return Collections.unmodifiableList(this.addedMessageIds);
/*     */   }
/*     */   
/*     */   public Mailbox getMailbox() {
/* 558 */     return this.mailbox;
/*     */   }
/*     */   
/*     */   public Object getContent() {
/* 562 */     return "";
/*     */   }
/*     */   
/*     */   public String getContentType()
/*     */   {
/* 567 */     return "text/plain";
/*     */   }
/*     */   
/*     */   public MailAdapter.Address[] parseAddresses(String headerName)
/*     */   {
/*     */     MimeMessage msg;
/*     */     try {
/* 574 */       msg = this.handler.getMimeMessage();
/*     */     } catch (ServiceException e) {
/* 576 */       ZimbraLog.filter.warn("Unable to get MimeMessage.", e);
/* 577 */       return FilterAddress.EMPTY_ADDRESS_ARRAY;
/*     */     }
/*     */     
/* 580 */     String[] hdrValues = null;
/*     */     try {
/* 582 */       hdrValues = msg.getHeader(headerName);
/*     */     } catch (MessagingException e) {
/* 584 */       ZimbraLog.filter.warn("Unable to get headers named '%s'", headerName, e);
/*     */     }
/* 586 */     if (hdrValues == null) {
/* 587 */       return FilterAddress.EMPTY_ADDRESS_ARRAY;
/*     */     }
/*     */     
/* 590 */     List<MailAdapter.Address> retVal = new LinkedList();
/* 591 */     for (String hdrValue : hdrValues) {
/* 592 */       for (com.zimbra.common.mime.InternetAddress addr : com.zimbra.common.mime.InternetAddress.parseHeader(hdrValue)) {
/* 593 */         String emailAddr = addr.getAddress();
/* 594 */         if ((emailAddr != null) && (emailAddr.contains("@")))
/* 595 */           retVal.add(new FilterAddress(emailAddr));
/*     */       }
/*     */     }
/* 598 */     return (MailAdapter.Address[])retVal.toArray(new MailAdapter.Address[retVal.size()]);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public boolean isInBodyText(String substring)
/*     */   {
/* 605 */     return false;
/*     */   }
/*     */   
/*     */   public void setDiscardActionPresent() {
/* 609 */     this.discardActionPresent = true;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/filter/ZimbraMailAdapter.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */